package net 
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.ObjectEncoding;
	import flash.net.registerClassAlias;
	import flash.net.Socket;
	/**
	 * ...
	 * @author zxx
	 */
	public class NetClient
	{
		public var OnConnected:Function;
		public var OnDisconnected:Function;

		private var CallbackList:Array;
		private var socket:Socket;
		private var _Connected:Boolean;
		
		public function NetClient() 
		{
			CallbackList = new Array();
		}
		
		public function RegisterMessageCallback(MessageType:int, Callback:Function):void
		{
			CallbackList[MessageType] = Callback;
		}
		
		public function Open(ServerIp:String, ServerPort:int):Boolean
		{
			socket = new Socket();
			socket.addEventListener(Event.CONNECT, onHandler);
			socket.addEventListener(Event.CLOSE, onHandler);
			socket.addEventListener(IOErrorEvent.IO_ERROR, onHandler);
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onHandler);
			socket.addEventListener(ProgressEvent.SOCKET_DATA, onHandler);  
			socket.objectEncoding = ObjectEncoding.AMF3;
			try
			{
				socket.connect(ServerIp, ServerPort); 
			}
			catch (e:*)
			{
				return false;
			}
			return true;
		}
		
		public function SendMessage(aMessage:MessageBase):Boolean
		{
			if (socket.connected)
			{
				try
				{
					socket.writeObject(aMessage);
					socket.flush();
					return true;
				}
				catch (e:*)
				{
					socket.close();
					CallDisconnected();
				}
			}
			return false;
		}
		
		public function get Connected():Boolean
		{
			return _Connected;
		}
		
		public function  onHandler(event:Event):void
		{
			switch(event.type) 
			{  
				case ProgressEvent.SOCKET_DATA:
					var aMessage:MessageBase;
					try
					{
						aMessage = MessageBase(socket.readObject());
					}
					catch (e:*)
					{
						//可能:数据错误或数据不完整，不处理。
						break;
					}
					CallMessageCallback(aMessage);
					break;  
				case Event.CLOSE:  
					CallDisconnected();
					break;  
				case Event.CONNECT:  
					CallOnConnected();
					break;  
				case IOErrorEvent.IO_ERROR:
				case SecurityErrorEvent.SECURITY_ERROR:  
					CallDisconnected();
					break;  
			}    
		}
		
		private function CallMessageCallback(aMessage:MessageBase):void
		{
			if (CallbackList[aMessage.MessageType] != null)
			{
				CallbackList[aMessage.MessageType](aMessage);
			}
		}
		
		private function CallOnConnected():void
		{
			_Connected = true;
			if (OnConnected != null)
			{
				OnConnected();
			}
		}
		
		private function CallDisconnected():void
		{
			_Connected = false;
			if (OnDisconnected != null)
			{
				OnDisconnected();
			}
		}
		
	}

}